home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / tiff / tiffdum4.c < prev    next >
C/C++ Source or Header  |  1988-11-02  |  9KB  |  375 lines

  1. /* tiffdump - dump a tiff file, to avoid painful hex dumps
  2.  */
  3. #include "aldtypes.h"
  4. #include "imtypes.h"
  5. #include "tiff.h"
  6. #include "imag.h"
  7. #include "imtiff.h"
  8. #include "vio.h"
  9. #include "stdio.h"
  10. #include "dloc.h"
  11.  
  12. /* prototypes:
  13.  */
  14. #ifdef MACINTOSH
  15. FILE * fopen (char *, char *);
  16. int fseek (FILE *, long, int);
  17. int fread (char *, int, int, FILE *);
  18. int fclose (FILE *);
  19. #endif
  20.  
  21.  
  22. static struct {
  23.     WORD    tag;
  24.      char    *str;
  25. } tagstr[] = {
  26. TGNEWSUBFILETYPE,            "NewSubfileType",
  27. TGOLDSUBFILETYPE,            "OldSubfileType",
  28. TGIMAGEWIDTH,                "ImageWidth",
  29. TGIMAGELENGTH,                "ImageLength",
  30. TGCOMPRESSION,                "Compression",
  31. TGPHOTOMETRICINTERPRETATION,"PhotometricInterp",
  32. TGTHRESHHOLDING,            "Threshholding",
  33. TGCELLWIDTH,                "CellWidth",
  34. TGCELLLENGTH,                "CellLength",
  35. TGFILLORDER,                "FillOrder",
  36. TGSTRIPOFFSETS,                "StripOffsets",
  37. TGORIENTATION,                "Orientation",
  38. TGSAMPLESPERPIXEL,            "SamplesPerPixel",
  39. TGBITSPERSAMPLE,            "BitsPerSample",
  40. TGROWSPERSTRIP,                "RowsPerStrip",
  41. TGSTRIPBYTECOUNTS,            "StripByteCounts",
  42. TGMINSAMPLEVALUE,            "MinSampleValue",
  43. TGMAXSAMPLEVALUE,            "MaxSampleValue",
  44. TGXRESOLUTION,                "XResolution",
  45. TGYRESOLUTION,                "YResolution",
  46. TGPLANARCONFIGURATION,        "PlanarConfiguration",
  47. TGDOCUMENTNAME,                "DocumentName",
  48. TGPAGENAME,                    "PageName",
  49. TGXPOSITION,                "XPosition",
  50. TGYPOSITION,                "YPosition",
  51. TGIMAGEDESCRIPTION,            "ImageDescription",
  52. TGMAKE,                        "Make",
  53. TGMODEL,                    "Model",
  54. TGFREEOFFSETS,                "FreeOffsets",
  55. TGFREEBYTECOUNTS,            "FreeByteCounts",
  56. TGGRAYUNIT,                    "GrayUnit",
  57. TGGRAYCURVE,                "GrayCurve",
  58. TGRESOLUTIONUNIT,            "ResolutionUnit",
  59. TGPAGENUMBER,                "PageNumber",
  60. TGCOLORRESPONSECURVES,        "ColorResponseCurves",
  61. TGSOFTWARE,                    "Software",
  62. TGDATETIME,                    "DateTime",
  63. TGARTIST,                    "Artist",
  64. TGHOSTCOMPUTER,                "HostComputer",
  65. TGPREDICTOR,                "Predictor",
  66. TGWHITEPOINT,                "WhitePoint",
  67. TGPRIMARYCHROMATICITIES,    "PrimaryChromaticities",
  68. TGCOLORMAP,                    "ColorMap",
  69.  
  70. };
  71.  
  72. /* a particularly greasy static:
  73.  */
  74. DWORD TiffStart = 0L;
  75.  
  76. /***************************** subroutines ***************************/
  77.  
  78.  
  79. /* get tag string
  80.  */
  81. static char defstr[] = "(no string avail)";
  82. void GtTagString (WORD, char **);
  83. LOCAL void GtTagString (tag, ps)
  84. WORD    tag;
  85. char    **ps;
  86. {
  87.         int tablen;
  88.         int ii;
  89.  
  90.         tablen = sizeof (tagstr) / sizeof (tagstr[0]);
  91.         for (ii = 0; ii < tablen; ii++) {
  92.             if (tag == tagstr[ii].tag) {
  93.                 *ps = tagstr[ii].str;
  94.                 return;
  95.             }
  96.         }
  97.         *ps = defstr;
  98. }
  99.  
  100. /* dump an entry
  101.  */
  102. #define MAXVAL 100
  103.  
  104. RC dumpentry (PDLOC, WORD, DWORD, DIRENTRY *);
  105.  
  106. LOCAL RC dumpentry (pDloc, ByteOrder, pos, pde)
  107. PDLOC        pDloc;
  108. WORD        ByteOrder;    /* INTELTIFF vs MOTOROLATIFF */
  109. DWORD        pos;
  110. DIRENTRY    *pde;
  111. {
  112.         RC        err;
  113.         WORD    tsize;
  114.         WORD    BytesToRead;
  115.         char    *bufptr;
  116.         union {
  117.             char    bytes[MAXVAL];
  118.             DWORD    dword;
  119.         } buf;
  120.         WORD    maxitems;
  121.         WORD    item;
  122.         char    *s;
  123.         DWORD    valpos;
  124.         DWORD    ValBuf;
  125.         int        red;
  126.         
  127.         /* get the non byte reversed value
  128.          */
  129.         if (err = VRead (pDloc, pos + 8L, sizeof(ValBuf), (LPSTR)&ValBuf)) {
  130.              DBMSG(("dumpentry: VRead error\n"));
  131.              return err;
  132.         }
  133.         
  134.         /* dump the basic entry
  135.          */
  136.         GtTagString (pde->deTag, &s);
  137.         DBMSG(("%6lu  tag=%5u [%-20.20s] type=%u length=%lu val=0x%.8lx\n",
  138.          pos, pde->deTag, s, pde->deType, pde->deLength, ValBuf));
  139.  
  140.         /* print out the value intelligently
  141.          */
  142.         if (err = GtTiffSizeof (pde->deType, &tsize)) {
  143.             DBMSG(("dumpentry: GtTiffSizeof error\n"));
  144.             return err;
  145.         }
  146.         BytesToRead = tsize * pde->deLength;
  147.         maxitems = MAXVAL / tsize;
  148.         maxitems = (pde->deLength < (DWORD) maxitems) ?
  149.          (WORD)(pde->deLength) : maxitems;
  150.         /* careful here: we can't just use deVal to grab data out of, since
  151.          * may already have been byte-reversed!
  152.          */
  153.         if (BytesToRead <= 4)
  154.             valpos = pos + 8L;    /* deVal starts on byte 8, wit de */
  155.         else
  156.             valpos = pde->deVal;
  157.         if (err = GtData (pDloc, ByteOrder, valpos, maxitems, pde->deType, buf.bytes)) {
  158.             DBMSG(( "dumpentry: GtData error\n"));
  159.             return err;
  160.         }
  161.  
  162.         bufptr = buf.bytes;
  163.         
  164.         switch (pde->deType) {
  165.         case TIFFBYTE:
  166.             for (item = 0; item < maxitems; item++)
  167.                 DBMSG(("%x", (unsigned)(*bufptr++)));
  168.             DBMSG(("\n"));
  169.             break;
  170.         case TIFFASCII:
  171.             if (maxitems == 0)
  172.                 break;
  173.             DBMSG(("%.*s\n", maxitems, bufptr));
  174.             break;
  175.         case TIFFSHORT:
  176.             for (item = 0; item < maxitems; item++, bufptr += 2)
  177.                 DBMSG(("%u ", *((WORD *)bufptr)));
  178.             DBMSG(("\n"));
  179.             break;
  180.         case TIFFLONG:
  181.             for (item = 0; item < maxitems; item++, bufptr += 4)
  182.                 DBMSG(("%lu ", *((DWORD *)bufptr)));
  183.             DBMSG(("\n"));
  184.             break;
  185.         case TIFFRATIONAL:
  186.             for (item = 0; item < maxitems; item++) {
  187.                 DBMSG(("% lu ", *((DWORD *)bufptr)));
  188.                 bufptr += 4;
  189.                 DBMSG(("%lu ", *((DWORD *)bufptr)));
  190.                 bufptr += 4;
  191.             }
  192.             DBMSG(("\n"));
  193.             break;
  194.         default:
  195.             DBMSG(( "dumpentry: can't get here\n"));
  196.             break;
  197.         }
  198.         return SUCCESS;
  199. }
  200.  
  201.  
  202.  
  203. /***************************** main routine **************************/
  204. #ifdef WINDOWS
  205. int main (int,char **);
  206. int main (ac, av)
  207. #endif
  208.  
  209. #ifdef MACINTOSH
  210. int _main (int, char **);
  211. int _main (ac, av)
  212. #endif
  213.  
  214. int ac;
  215. char **av;
  216. {
  217.          RC            err;
  218.          TIFFHDR        th;
  219.          DIRENTRY    de;
  220.          WORD        entries;
  221.         WORD        entry;
  222.          DWORD        location;
  223.         DLOC        dloc;
  224.         DWORD        dwtemp;
  225.         WORD        wtemp;
  226.         WORD        ByteOrder;
  227.         WORD        red;
  228.          
  229.          
  230.          /* check # of args
  231.           */
  232.          if (ac != 2) {
  233.              DBMSG(("usage: tiffdump  filename\n"));
  234.              goto cu0;
  235.          }
  236.          
  237.          /* open the file
  238.           */
  239.          if ((dloc.dlFp = fopen (av[1], "rb")) == (FILE *) NULL) {
  240.              DBMSG(("can't open %s\n", av[1]));
  241.              goto cu0;
  242.          }
  243.          DBMSG(("FILE: %s\n", av[1]));
  244.         dloc.dlWhere = INFILE;
  245.  
  246.         /* since I use this program to dump TIFF "files" that are embedded in
  247.          * other files (a nonstandard thing to do), I will look for a
  248.          * plausible start of the TIFF section.  TODO: make this more
  249.          * general (cycle through TIFF "files") and more robust (check for
  250.          * version #, at least).
  251.          */
  252.         while ((red = fread ((char *)&ByteOrder, sizeof(WORD), 1, dloc.dlFp)) == 1) {
  253.             if (ByteOrder == INTELTIFF || ByteOrder == MOTOROLATIFF)
  254.                 break;
  255.             else
  256.                 TiffStart += 2L;
  257.         }
  258.         DBMSG(("TiffStart=%lu\n",TiffStart));
  259.         DBMSG(("ByteOrder=%x\n",ByteOrder));
  260.         if (red == 0) {
  261.             DBMSG(("can't find ByteOrder\n"));
  262.             goto quit;
  263.         }
  264. #if 0
  265.         dloc.dlOrder = ByteOrder;
  266. #endif /* 0 */
  267.  
  268.          /* read the 8-byte header, and dump it
  269.           */
  270.          if (err = GtTiffHdr ((PDLOC)&dloc, &th)) {
  271.              DBMSG(("can't read header\n"));
  272.              goto quit;
  273.          }
  274.          if (th.thByteOrder == INTELTIFF)
  275.              DBMSG(("%6lu  ByteOrder = INTELTIFF\n", 0L));
  276.          else if (th.thByteOrder == MOTOROLATIFF)
  277.              DBMSG(("%6lu  ByteOrder = MOTOROLATIFF\n", 0L));
  278.         else {
  279.             DBMSG(("bad byte order.\n"));
  280.             goto quit;
  281.         }
  282.          DBMSG(("%6lu  Version = %d\n", 2L, th.thVersion));
  283.          DBMSG(("%6lu  IfdOffset = %lu\n", 4L, th.thIfdOffset));
  284.          
  285.          location = th.thIfdOffset;
  286. #if 0
  287.         dloc.dlOrder = th.thByteOrder;
  288. #endif /* 0 */
  289.          
  290.          /* loop through the IFD's
  291.           */
  292.          do {
  293.              /* if ifd location is 0, quit
  294.               */
  295.              if (location == 0L) {
  296.                  DBMSG(("ifd at 0. quit.\n"));
  297.                  break;
  298.              }
  299.          
  300.              /* read the number of entries, and dump it
  301.               */
  302.              if (err = GtData ((PDLOC)&dloc, th.thByteOrder, (DWORD)location, 1, TIFFSHORT,
  303.               (LPSTR)&entries)) {
  304.                  DBMSG(("can't read # of entries\n"));
  305.                  break;
  306.              }
  307.              DBMSG(("\n%6lu  Entries = %d\n", th.thIfdOffset, entries));
  308.              if (entries == 0) {
  309.                  DBMSG(("number of entries is 0. quit.\n"));
  310.                  break;
  311.              }
  312.              location += 2;
  313.          
  314.              /* loop through the entries
  315.               */
  316.              for (entry = 0; entry < entries; entry++) {
  317.              
  318.                  /* read the entry
  319.                   */
  320.                  if (err = GtTiffEntry ((PDLOC)&dloc, th.thByteOrder, location, &de)) {
  321.                      DBMSG(("can't read entry\n"));
  322.                      goto quit;
  323.                  }
  324.                  
  325.                  /* print the entry in human-readable form
  326.                   */
  327.                 if (err = dumpentry ((PDLOC)&dloc, th.thByteOrder, location, &de)) {
  328.                     DBMSG(("dumpentry error\n"));
  329.                     goto quit;
  330.                 }
  331.                 
  332.                 /* store the value, for future diagnostic use
  333.                  */
  334.                  
  335.                  /* adjust the current location
  336.                   */
  337.                  location += sizeof (DIRENTRY);
  338.                  
  339.              } /* end of entry loop */
  340.              
  341.              /* read the location of the next ifd
  342.               */
  343.              if (err = GtData((PDLOC)&dloc, th.thByteOrder, (DWORD)location, 1, TIFFLONG,
  344.               (LPSTR)&dwtemp)) {
  345.                  DBMSG(("%6lu  can't read location of the next ifd\n",
  346.                   location));
  347.                  goto quit;
  348.              }    
  349.              DBMSG(("%6lu  next ifd at %lu\n", location, dwtemp));
  350.              location = dwtemp;
  351.              
  352.          } while (1); /* end of ifd loop */
  353.          
  354.          /* now check for errors.  We go through a lot of the same work again, since
  355.           * this error-checking was an afterthought.
  356.           */
  357.          {
  358.              IMAG    imag;
  359.              IMAG    *p = &imag;
  360.              
  361.              DBMSG(("\n\n"));
  362.              
  363.              if (err = GtTiffInfo ((PDLOC)&dloc, p)) {
  364.                  /* DBMSG(("tiffdump: GtTiffInfo\n")); */
  365.                  goto b0;
  366.              }
  367.              
  368. b1:            CloseImag(p);
  369. b0:            ;
  370.          }
  371.          
  372. quit:    ;
  373.          fclose (dloc.dlFp);
  374. cu0:    return;
  375. }